﻿#include <Python.h> //放在qt相关的头文件之前，避免冲突
#include "PyInterpreter.h"

#include <QCoreApplication>
#include <QDir>
#include <QByteArray>
#include <QReadWriteLock>
#include <QDebug>
#include <iostream>

#include "PythonAgent.h"
#include "BaseModule/GlobalEnums.h"
#include "BaseModule/IBaseSignal.h"

namespace ScriptManager
{
    PyInterpreter::~PyInterpreter()
    {
        if (Py_IsInitialized())
        {
            Py_Finalize();
        }
    }

    bool PyInterpreter::init(PythonAgent* agent, QString pythonPath)
    {
#ifdef Q_OS_WIN32
        Py_SetPythonHome(pythonPath.toStdWString().c_str());
#endif
        Py_Initialize();
        PyEval_InitThreads(); // 启用线程支持

        if (!Py_IsInitialized())
            return false;

        _agent = agent;
        PyErr_PrintEx(1);
        this->execCode("import sys", false);
        this->execCode("import os", false);
        this->execCode("import scipy", false);//波形分析相关库
        this->execCode("import numpy", false);//波形分析相关库
        this->execCode("from scipy import signal", false);//波形分析相关库
        QString path = QDir::cleanPath(qApp->applicationDirPath()) + "/scripts";
        QString qs = QString("sys.path.append(\"%1\")").arg(path);
        this->execCode(qs, false);

        QDir dir(path);
        QStringList suffix;
        suffix << "*.py";
        dir.setNameFilters(suffix);
        QList<QFileInfo> files = dir.entryInfoList(suffix);
        for (int i = 0; i < files.size(); ++i)
        {
            QFileInfo fileinfo = files.at(i);
            QString name = fileinfo.baseName();
            QString command = QString("import %1").arg(name);
            this->execCode(command, false);
        }

        return true;
    }

    int PyInterpreter::execCode(QString code, bool save)
    {
        QReadWriteLock lock;
        lock.lockForRead();
        std::string s = code.toStdString();
        const char* c = s.c_str();
        qDebug() << "exec: " << code;

        int ok = PyRun_SimpleStringFlags(c, NULL);

        if (save)
            _codelist.append(code);

        if (ok == -1)
        {
            // 调用python执行失败
            QString error = tr("Exception occurred at: \"%1\"").arg(code);
            emit IBaseSignalInstance->signal_showMessageToConsole(BaseModule::EMessageConsole::Warning, error);
            emit IBaseSignalInstance->signal_pythonExecFailed();
            _agent->stopScript();
        }

        lock.unlock();
        return ok;
    }

    void PyInterpreter::execFile(QString file)
    {
        QByteArray la = file.toLocal8Bit();
        char* c = la.data();
        FILE* fp = nullptr;
        fp = fopen(c, "r");
        if (fp != nullptr)
        {
            PyRun_SimpleFile(fp, c);
        }
    }

    int PyInterpreter::getCodeCount()
    {
        return _codelist.size();
    }

    QString PyInterpreter::getCodeAt(int i)
    {
        QString c;
        if (i >= 0 && i < _codelist.size())
            c = _codelist.at(i);
        return c;
    }

    void PyInterpreter::codeListAppend(QString qs)
    {
        _codelist.append(qs);
    }

    QStringList PyInterpreter::getCode()
    {
        return _codelist;
    }

    void PyInterpreter::clearCode()
    {
        _codelist.clear();
    }
} // namespace ScriptManager
